# include "Quests.h"

# include "World.h"
# include "Hero.h"
# include "Enemy.h"
# include "PNJ.h"

Quests::Quests()
{

}

Quests::~Quests()
{

}

std::map<std::string, Quest*>& Quests::getQuestsCurrent()
{
	return myQuestsCurrent;
}

std::map<std::string, Quest*>& Quests::getQuestsDone()
{
	return myQuestsDone;
}

void Quests::init( World* world, Hero* hero, const std::string& lua)
{
	myWorld = world;
	myHero = hero;

	myLua = lua;

	myQuestsOpen.insert( std::pair<std::string, std::string*>( "First", new std::string( "PNJ1")));
}

void Quests::updateWorld()
{
	for ( std::map<std::string, std::string*>::iterator it = myQuestsOpen.begin(); it != myQuestsOpen.end(); it++ )
	{
		PNJ* pnjTmp = myWorld->findPNJName( *it->second);
		
		if ( pnjTmp )
		{
			pnjTmp->loadQuest( it->first, 0);
		}
	}
	
	for ( std::map<std::string, Quest*>::iterator it = myQuestsCurrent.begin(); it != myQuestsCurrent.end(); it++ )
	{
		switch ( it->second->actions[it->second->current] )
		{
			case QUEST_KILL:
			{
				Enemy* targetTmp = myWorld->findEnemyName( *it->second->targets[it->second->current]);
				
				if ( targetTmp )
				{
					targetTmp->activateQuest( it->second);
				}
			}
			break;

			case QUEST_TALK:
			{
				PNJ* targetTmp = myWorld->findPNJName( *it->second->targets[it->second->current]);
			
				if ( targetTmp )
				{
					targetTmp->loadQuest( it->second->name, it->second->current);
				}
			}
			break;
		}
	}
}

void Quests::activeQuest( const std::string& questName)
{
	lua_State* stateTmp = lua_open();
	luaL_openlibs( stateTmp);
	luaL_dofile( stateTmp, myLua.c_str());
	lua_settop( stateTmp, 0);
	int indiceTmp = 2;

	lua_getglobal( stateTmp, questName.c_str());
	
	myQuestsCurrent.insert( std::pair<std::string, Quest*>( questName, new Quest()));

	myQuestsCurrent[questName]->name = questName;
	myQuestsCurrent[questName]->current = -1;

	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	myQuestsCurrent[questName]->description = lua_tostring( stateTmp, -1);
	lua_pop( stateTmp, 1);
		
	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	myQuestsCurrent[questName]->rewardExp = lua_tonumber( stateTmp, -1);
	lua_pop( stateTmp, 1);
	
	lua_pushnumber( stateTmp, indiceTmp++);
	lua_gettable( stateTmp, -2);
	unsigned int numberTmp = lua_tonumber( stateTmp, -1);
	lua_pop( stateTmp, 1);

	for ( unsigned int i = 0; i < numberTmp; i++ )
	{
		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myQuestsCurrent[questName]->actions.push_back( lua_tonumber( stateTmp, -1));
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myQuestsCurrent[questName]->targets.push_back( new std::string( lua_tostring( stateTmp, -1)));
		lua_pop( stateTmp, 1);

		lua_pushnumber( stateTmp, indiceTmp++);
		lua_gettable( stateTmp, -2);
		myQuestsCurrent[questName]->descriptions.push_back( new std::string( lua_tostring( stateTmp, -1)));
		lua_pop( stateTmp, 1);
	}

	lua_pop( stateTmp, 1);
	lua_close( stateTmp);

	delete myQuestsOpen[questName];
	myQuestsOpen.erase( questName);

	nextStepQuest( questName);
}

void Quests::nextStepQuest( const std::string& questName)
{
	Quest* questTmp = myQuestsCurrent.find( questName)->second;

	questTmp->current++;

	if ( questTmp->current == questTmp->actions.size() )
	{
		completeQuest( questName);
	}

	else
	{
		switch ( questTmp->actions[questTmp->current] )
		{
			case QUEST_KILL:
			{
				Enemy* target = myWorld->findEnemyName( *questTmp->targets[questTmp->current]);
				
				if ( target )
				{
					target->activateQuest( questTmp);
				}
			}
			break;

			case QUEST_TALK:
			{
				PNJ* target = myWorld->findPNJName( *questTmp->targets[questTmp->current]);
			
				if ( target )
				{
					target->activateQuest( questTmp);
				}
			}
			break;
		}
	}
}

void Quests::completeQuest( const std::string& questName)
{
	std::map<std::string, Quest*>::iterator questTmp = myQuestsCurrent.find( questName);

	myHero->addExperience( questTmp->second->rewardExp);

	for ( unsigned int i = 0; i < questTmp->second->rewardObject.size(); i++ )
	{

	}

	lua_State* stateTmp = lua_open();
	luaL_openlibs( stateTmp);
	luaL_dofile( stateTmp, myLua.c_str());
	lua_settop( stateTmp, 0);

	for ( unsigned int i = 0; i < questTmp->second->rewardQuests.size(); i++ )
	{
		lua_getglobal( stateTmp, questTmp->second->rewardQuests[i]->c_str());
		lua_pushnumber( stateTmp, 1);
		lua_gettable( stateTmp, -2);
		myQuestsOpen.insert( std::pair<std::string, std::string*>( questTmp->second->rewardQuests[i]->c_str(), new std::string( lua_tostring( stateTmp, -1))));
		lua_pop( stateTmp, 2);
	}

	myQuestsDone.insert( std::pair<std::string, Quest*>( questTmp->first, questTmp->second));
	myQuestsCurrent.erase( questTmp);
}

bool Quests::isCurrentEmpty()
{
	return myQuestsCurrent.empty();
}

bool Quests::isDoneEmpty()
{
	return myQuestsDone.empty();
}

Quest* Quests::findQuest( const std::string& questName)
{
	if ( myQuestsCurrent.find( questName) != myQuestsCurrent.end() )
	{
		return myQuestsCurrent.find( questName)->second;
	}

	if ( myQuestsDone.find( questName) != myQuestsDone.end() )
	{
		return myQuestsDone.find( questName)->second;
	}

	return NULL;
}